﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Wormhole.Engine.Communication
{
	/// <author>Hannes Foulds</author>
	/// <date>26 September 2008</date>
	/// <summary>
	/// This class is used to receive events from the other player over the communication channel.
	/// </summary>
	public class Receiver : Listener
	{
		#region Constructor
		/// <summary>
		/// Initialize a new instance of the class.
		/// </summary>
		/// <param name="game">The game object.</param>
		/// <param name="channel">The communications channel</param>
		public Receiver(Wormhole.Engine.Game game, Wormhole.Engine.Communication.IClient channel)
			: base(game, channel)
		{
		}
		#endregion

		#region Initialize Game Events
		/// <summary>
		/// Wire up the events for the game object.
		/// </summary>
		protected override void InitializeGameEvents()
		{
		}
		#endregion

		#region Initialize Channel Events
		/// <summary>
		/// Wire up the events for the communications channel.
		/// </summary>
		protected override void InitialzeChannelEvents()
		{
			this.Channel.GameAction += new GameActionDelegate(Channel_GameAction);
			this.Channel.KeptHand += new KeptHandDelegate(Channel_KeptHand);
			this.Channel.TookMulligan += new TookMulliganDelegate(Channel_TookMulligan);

			this.Channel.CardAction += new CardActionDelegate(Channel_CardAction);
		}
		#endregion

		#region Event Handlers


		#region Game Action
		/// <summary>
		/// Handle game actions received.
		/// </summary>
		/// <param name="action"></param>
		void Channel_GameAction(Wormhole.Engine.Communication.Action.GameAction action)
		{
			switch (action.Action)
			{
				case Action.GameActionType.GameTurnAction :
					this.ProcessGameTurnAction(action);
					break;
			}
		}
		#endregion

		#region Kept Hand
		/// <summary>
		/// Handle the message indicating that the opponent kept his hand.
		/// </summary>
		private void Channel_KeptHand()
		{
			this.Game.Player2.KeepHand();

			// start the game turn
			if (this.Game.GameCreator)
				this.Game.GameTurn.StartTurn();
		}
		#endregion

		#region Took Mulligan
		/// <summary>
		/// A message was received that the opponent took a mulligan.
		/// </summary>
		private void Channel_TookMulligan()
		{	
			this.Game.Player2.TakeMulligan();

			// start the game turn
			if (this.Game.GameCreator)
				this.Game.GameTurn.StartTurn();
		}
		#endregion

		#region Card Action
		/// <summary>
		/// Handle a card action that was performed by the opponent.
		/// </summary>
		/// <param name="action"></param>
		void Channel_CardAction(Wormhole.Engine.Communication.Action.CardAction action)
		{
			switch (action.Action)
			{
				case Action.CardActionType.Assign:
					this.AssignCard(action);
					break;
				case Action.CardActionType.Play:
					this.PlayCard(action);
					break;
				case Action.CardActionType.AssignMissionGlyph:
					this.AssignMissionGlyph(action);
					break;
				case Action.CardActionType.ReplaceMissionBottom:
					this.ReplaceMissionBottom(action);
					break;
			}
		}
		#endregion

		#endregion

		#region Assign Card
		/// <summary>
		/// Assign a card.
		/// </summary>
		/// <param name="action">The action that was received</param>
		protected void AssignCard(Wormhole.Engine.Communication.Action.CardAction action)
		{
			// find the card to assign
			CardLibrary.BaseCardTypes.SkillsCard card = this.Game.Player2.AllCards.FindByID(action.CardID) as CardLibrary.BaseCardTypes.SkillsCard;

			// assign the card
			card.Assign();
		}
		#endregion

		#region Play Card
		/// <summary>
		/// Play a card.
		/// </summary>
		/// <param name="action">The action that was received</param>
		protected void PlayCard(Wormhole.Engine.Communication.Action.CardAction action)
		{
			// find the card to assign
			CardLibrary.BaseCardTypes.Card card = this.Game.Player2.AllCards.FindByID(action.CardID);

			// assign the card
			card.Play();
		}
		#endregion
			
		#region Process Game Turn Action
		/// <summary>
		/// Process a game turn action
		/// </summary>
		/// <param name="action"></param>
		private void ProcessGameTurnAction(Wormhole.Engine.Communication.Action.GameAction action)
		{
			Wormhole.Engine.Turn.GameTurnAction turnAction = Communication.EnumConvertor<Wormhole.Engine.Turn.GameTurnAction>.FromString(action.Target);
			switch (turnAction)
			{
				case Wormhole.Engine.Turn.GameTurnAction.Pass:
					if (this.Game.GameTurn.CurrentPhase == Wormhole.Engine.Turn.Phase.PerformAction)
						this.Game.GameTurn.PassActionPhase(null);
					break;
				case Wormhole.Engine.Turn.GameTurnAction.ContinueMissions:
					this.ContinueMissions(true);
					break;
				case Wormhole.Engine.Turn.GameTurnAction.StopMissions:
					this.ContinueMissions(false);
					break;
				case Wormhole.Engine.Turn.GameTurnAction.AskMulligan:
					this.AskMulligan();
					break;
			}
		}
		#endregion

		#region Assign Mission Glyph
		/// <summary>
		/// Assign the mission glyph to a character
		/// </summary>
		/// <param name="action">The action that was received</param>
		protected void AssignMissionGlyph(Wormhole.Engine.Communication.Action.CardAction action)
		{
			// find the characted
			CardLibrary.CardTypes.Character card = this.Game.Player2.AllCards.FindByID(action.CardID) as CardLibrary.CardTypes.Character;

			// create the response that should be passed to the mission method
			Input.Response response = new Input.Response();
			response.SelectedCards = new Wormhole.Engine.Decks.Deck();
			response.SelectedCards.Add(card);

			// call the mission method to complete the glyph assignment
			this.Game.Mission.AssignGlyph(response);
		}
		#endregion

		#region Continue Missions
		/// <summary>
		/// Handle the continue missions message.
		/// </summary>
		/// <param name="continueMissions">Does the opponent want to play another mission.</param>
		protected void ContinueMissions(bool continueMissions)
		{
			if (this.Game.GameTurn.CurrentPhase == Wormhole.Engine.Turn.Phase.DecideContinue)
			{
				// create the response object
				Input.Response response = new Input.Response();
				response.ResponseType = continueMissions ? Input.ResponseType.Yes : Input.ResponseType.No;

				// complete the action phase
				this.Game.GameTurn.CompleteProcessDecideContinuePhase(response);
			}
		}
		#endregion

		#region Continue Missions
		/// <summary>
		/// Handle the message to replace a mission to the bottom of the mission pile.
		/// </summary>
		/// <param name="action">The action that was received</param>
		protected void ReplaceMissionBottom(Wormhole.Engine.Communication.Action.CardAction action)
		{
			// find the mission card
			CardLibrary.BaseCardTypes.Card card = this.Game.Player2.AllCards.FindByID(action.CardID);

			// create the response that should be passed to the mission method
			Input.Response response = new Input.Response();
			response.ResponseType = Wormhole.Engine.Input.ResponseType.SingleCardSelect;
			response.SelectedCards = new Wormhole.Engine.Decks.Deck();
			response.SelectedCards.Add(card);

			// complete the action phase
			this.Game.Mission.ReplaceMission(response);
		}
		#endregion

		#region Ask Mulligan
		/// <summary>
		/// Ask wheter or not to perform a mulligan.
		/// </summary>
		protected void AskMulligan()
		{
			this.Game.AskMulligan();
		}
		#endregion
	}
}
